﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DotNetCommon.Web.Middlewares
{
    /// <summary>
    /// 访问统计中间件
    /// </summary>
    public class RequestStatisticMiddleware
    {
        private readonly RequestDelegate next;
        private readonly ILogger<RequestStatisticMiddleware> logger;

        /// <summary>
        /// 构造函数只在构建请求管道的时候调用一次,不是每个请求都创建一次
        /// </summary>
        /// <param name="next"></param>
        /// <param name="logger"></param>
        public RequestStatisticMiddleware(RequestDelegate next, ILogger<RequestStatisticMiddleware> logger)
        {
            this.next = next;
            this.logger = logger;
        }

        private static long RunningCounter = 0;
        private static long TotalCounter = 0;

        /// <summary>
        /// override
        /// </summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public async Task InvokeAsync(HttpContext ctx)
        {
            var count = Interlocked.Increment(ref RunningCounter);
            var totalCount = Interlocked.Increment(ref TotalCounter);
            var st = new Stopwatch();
            st.Start();
            var requestInfo = $@"第{totalCount}个请求 当前并发:{count} 接收请求:{ctx.Request.Scheme}://{ctx.Request.Host}{ ctx.Request.Path}{ctx.Request.QueryString} 
     Method: {ctx.Request.Method}
     UA: {ctx.Request.Headers["User-Agent"]}
     Referer: {ctx.Request.Headers["Referer"]}
     Host: {ctx.Request.Host}
     Content-Type: {ctx.Request.ContentType}
     Content-Length: {ctx.Request.ContentLength} {(ctx.Request.ContentLength != null ? "约" + Math.Round((ctx.Request.ContentLength.Value / 1024.0), 2) + "KB" : "")}
     Client: {ctx.Connection.RemoteIpAddress}:{ctx.Connection.RemotePort}";
            try
            {
                await next(ctx);
                var counter2 = Interlocked.Decrement(ref RunningCounter);
                totalCount = Interlocked.Read(ref TotalCounter);
                st.Stop();
                var responseInfo = $@"

     响应 耗时:{st.ElapsedMilliseconds}毫秒 并发变化: {count}->{counter2} 当前总访问量:{totalCount}
        Status: {ctx.Response.StatusCode}
        Content-Type: {ctx.Response.ContentType}  
        Location: {ctx.Response.Headers["Location"]}
        Content-Length: {ctx.Response.ContentLength} {(ctx.Response.ContentLength != null ? "约" + Math.Round((ctx.Response.ContentLength.Value / 1024.0), 2) + "KB" : "")}";
                logger.LogInformation($"{requestInfo} {responseInfo}");
            }
            catch (Exception ex)
            {
                var counter2 = Interlocked.Decrement(ref RunningCounter);
                totalCount = Interlocked.Read(ref TotalCounter);
                st.Stop();
                var responseInfo = $@"

     响应异常Error 耗时:{st.ElapsedMilliseconds}毫秒 并发变化: {count}->{counter2} 当前总访问量:{totalCount}
        Messgae: {ex.Message}
        StackTrace: {ex?.StackTrace}  ";
                logger.LogInformation($"{requestInfo} {responseInfo}");
                if (ex.Message == "TokenExpired" && ex.StackTrace.Contains("at YW.Auth.Identity.VerfiyToken[T](String token, String deviceIdentity"))
                {
                    ctx.Response.StatusCode = 401;
                }
                else if (ex.Message == "InvalidToken")
                {
                    ctx.Response.StatusCode = 401;
                }
                else if (ex.Message == "MissingToken")
                {
                    ctx.Response.StatusCode = 401;
                }
                else
                {
                    throw ex;
                }
            }
        }
    }
}
